Implement generic marshalling type argument feature #28
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
As originally proposed in #21, this shifts the
MarshalAsAttributeandMarshalMapparameters out of theFromAction/FromFunc/FromFunctionPointer("factory methods") method argument lists into a generic type argument of the method (not the interface).A method call such as:
Would instead become:
IMarshaller<TSelf>This introduces the new
interface IMarshaller<TSelf>:Each of the factory methods now have both generic and non-generic overloads. The non-generic overloads will not provide any custom runtime marshalling behaviors. The generic methods take a single generic type parameter,
TMarshaller, which is constrained bywhere TMarshaller : IMarshaller<TMarshaller>, new(). Types implementingIMarshaller<TSelf>are not intended to be instanciated at runtime at all. This is a means to supply the custom marshallling behaviors at the call-site of the factory methods, which cannot be achieved through, for example, an attribute.Diagnostics
This PR removes all diagnostics that were previously generated, but the restrictions on the
MarshalAsAttributeandMarshalMapparameters are still in effect. I am undecided if the diagnostics should be added back in, or if a failure to parse the marshalling should be silently ignored.I am weighing the option of writing an analyzer to look for these issues specifically, as the analyzer can exist alongside the generator in the same assembly. This PR will not hinge on that decision.
CallingConvention
The factory methods still accept a
CallingConventionparameter, which creates potential conflict between the custom marshaller definition and the factory method argument. This is resolved in a similar fashion to a conflict between theMarshalMapand theMarshalAsAttributeproperties - the method argument is given precedence over the marshaller property.If the method argument can be statically parsed, then code generation is optimized (as previously implemented); otherwise if the method argument is explicitly specified (e.g., it is not defaulted), then its value will be parsed at runtime when the factory method is called.
If the method argument is omitted (defaulted), then a non-
nullvalue from the marshaller property will be used for optimal code generation.If the method argument is omitted (defaulted) for the non-generic methods (with no custom marshaller), the marshaller does not supply the
CallingConventionproperty, or the property isnull, then the final fallback will be to passCallingConvention.Winapias a runtime argument.Bug fixes
Because this PR touched so many files and lines of code, it may inadvertently have included bug fixes encountered along the way. It's equally possible that some of them were created along the way. Stopping work on this feature to try and create separate commits for each of these (including testing that they existed in the existing branch) was not a high priority.